#include <msp430x16x.h>

#include "adc.h"
#include "../timing/timing.h"

/*
  adcInit() sets the ADC registers to the standard values, sets the ADC and reference voltage on
  adcDisable() adcInit must have been run, sets the ADC and reference voltage off
  adcEnable(ref) adcInit must have been run, sets the ADC on, if ref=1 sets reference voltage on
  adcSample(inchx,srefx) samples a channel with the ADC
*/

void adcInit(void)
{
  /* Initialise Port */
  P6SEL |= 0x80; /* Set the Port 6 multiplexer to select ADC mode for P6.7 (10000000) */
  P6DIR |= ~0x80; /* Set P6.7 to input (X0000000) Won't be needed once all input/outputs are allocated */

  /* Initialise ADC */
  ADC12CTL0=0xAA40; /* Initialise ADC control register 0 (1010101001000000)*/
  /*  SHT1x=1010  SHT2x=1010 (512 clock cycle sample time, 102.4us at 5MHz)
      MSC=0  REF2_5V=1  REFON=0  ADC12ON=0  ADC12OVIE=0  ADC12TOVIE=0  ENC=0  ADC12SC=0 */
  ADC12CTL1=0x0200; /* Initialise ADC control register 1 (0000001000000000) */
  /*  CSTARTADDx=0000  SHSx=00  SHP=1  ISSH=0
      ADC12DIVx=000  ADC12SSELx=00  CONSEQx=00  ADC12BUSY=0 */
  ADC12IE=1; /* Enable interrupt vector for memory register 0 (0000000000000001) */
  /*  ADC12IE15=0  ADC12IE14=0  ADC12IE13=0  ADC12IE12=0  ADC12IE11=0  ADC12IE10=0  ADC12IE9=0  ADC12IE8=0
      ADC12IE7=0  ADC12IE6=0  ADC12IE5=0  ADC12IE4=0  ADC12IE3=0  ADC12IE2=0  ADC12IE1=0  ADC12IE0=1 */
}

void adcDisable(void)
{
  ADC12CTL0 &= ~(REFON | ADC12ON);
}

void adcEnable(char ref)
{
  /* Sets REFON=1 if argument is 1 */
  if (ref == 1)
  {
    ADC12CTL0 |= (REFON | ADC12ON);

    waitms(20); /* Delay to give reference voltage capacitors a chance to settle (17ms required) */
  }
  else
  {
    ADC12CTL0 |= (ADC12ON);
  }
}

int adcSample(char inchx, char srefx)
{
  int output;

  ADC12MCTL0 = ((srefx<<4)+inchx); /* Initialise ADC memory control register 0 */
  /* EOS=0, SREFx and INCHx should be looked up in slau049f pg368 */

  /* Start sampling and wait until ADC12MEM0 is filled, store ADC12MEM0 before ENC=0 to avoid corruption */
  ADC12CTL0 |= (ENC | ADC12SC);
  while (!(ADC12IFG & 0x1));
  output = ADC12MEM0;

  ADC12CTL0 &= ~ENC;

  return output;
}
